/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ro.pub.cs.dfsa.client;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import ro.pub.cs.dfsa.client.framework.RequestType;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import ro.pub.cs.dfsa.client.framework.Frame;
import ro.pub.cs.dfsa.client.framework.FrameFile;
import ro.pub.cs.dfsa.client.framework.Request;

/**
 *
 * @author Narcis
 */
public class DFSAClient {
    private int id;
    
    private String serverAddress;
    private int serverPort;
    
    private Socket clientSocket;
    private ObjectOutputStream oos;
    private ObjectInputStream ois;
    
    private int requestType;
    private String fileName;
    
    private static boolean noMoreFilesToList;
    
    public DFSAClient(int id, String serverAddress, int serverPort) {
       super(); 
       
       this.id = id;
       this.serverAddress = serverAddress;
       this.serverPort = serverPort;
       
       try {
            clientSocket = new Socket(serverAddress, serverPort);
       } catch (Exception e) {
            clientSocket = null;
       }
       
       File folder = new File(ClientConstants.DOWNLOAD_DIR + id);
       if (!folder.exists()) {
           try{
               folder.mkdir();
           } catch (Exception e){}
       }
    }
    
    public boolean isConnected() {
        //return clientSocket != null;
        if (clientSocket.isClosed())
            return false;
        else
            return true;
    }
    
    public void closeConnection() {
        if (isConnected()) {
            try {
                ois.close();
                oos.close();
                clientSocket.close();
            } catch (IOException e) { }
        }
    }
    
    public void setRequestType(int requestType) {
        this.requestType = requestType;
    }
    
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    
    public List<String> getFileNames() {
        if (noMoreFilesToList)
            return null;
        
        List<String> fileNames = new ArrayList<String>();
        
        try {            
            while (true) {
                Frame frame = (Frame) ois.readObject();
                
                if (frame.content == null)
                    break;
                                
                for (String fileName : frame.content)
                    fileNames.add(fileName);
                
                if (frame.lastFrame) {
                    noMoreFilesToList = true;
                    break;
                }
            }
        } catch (Exception e) {
            return null;
        }
        
        return fileNames;
    }
    
    public void executeRequest() {
        if (!isConnected())
            return;
                
        try {
            if (oos == null)
                oos = new ObjectOutputStream(clientSocket.getOutputStream());
            if (ois == null)
                ois = new ObjectInputStream(clientSocket.getInputStream());
        
            Request req = new Request();
            req.type = requestType;
            
            if (req.type == RequestType.UPLOAD) {
                req.name = fileName.substring(
                        fileName.lastIndexOf(File.separator.toString()) + 1);
            }
            else
                req.name = fileName;
            
            oos.writeObject(req);
            
            switch (requestType) {
                case RequestType.LIST:
                    noMoreFilesToList = false;
                    // restul logicii e executata de catre MainForm, prin
                    // apelarea repetitiva a lui getFileNames
                break;
                
                case RequestType.UPLOAD:
                    String completeUplFileName = fileName;
                    FileInputStream fis = new FileInputStream(completeUplFileName);
                    
                    int nrBytes = 0;
                    while (true) {
			FrameFile frame = new FrameFile();
			frame.content = new byte[ClientConstants.MAX_BYTES_PER_FILE_FRAME];
					
			nrBytes = fis.read(frame.content);
			if (nrBytes < ClientConstants.MAX_BYTES_PER_FILE_FRAME) {
                            frame.lastFrame = true;
                            oos.writeObject(frame);
                            break;
			}
			else {
                            frame.lastFrame = false;
                            oos.writeObject(frame);
			}
                    }
                break;
                
                case RequestType.DOWNLOAD:
                    String completeDldFileName = ClientConstants.DOWNLOAD_DIR + 
                            id + File.separatorChar + fileName;
                    
                    FileOutputStream fos = new FileOutputStream(completeDldFileName);
                    
                    FrameFile frame;
                    do {
                        frame = (FrameFile) ois.readObject();
                        fos.write(frame.content);
                    } while (!frame.lastFrame);
                    
                    fos.close();
                break;
                
                case RequestType.DELETE:
                    // nothing else to do because the Request
                    // has been already sent
                break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
